package dxn.nl.file.client.core;

import dxn.nl.file.client.model.dto.TransferMessageDto;
import dxn.nl.file.client.model.enums.ExportDealResultTypeEnum;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class ExportClientSocketManager {
    private static final Logger log = LoggerFactory.getLogger(ExportClientSocketManager.class);
    public static final String appSessionId = UUID.randomUUID().toString().replace("-","");

    public static List<ExportClientDealServer> dealServerList = new ArrayList<>();
    public static int nextServerInt = 0;

    private static ConcurrentHashMap<String, CompletableFuture> messageFutureMap = new ConcurrentHashMap<>();

    /**
     * 设置返回结果
     * @param csNioMessage
     */
    public static void dealFutureData(TransferMessageDto csNioMessage)
    {
        CompletableFuture future = messageFutureMap.get(csNioMessage.getConfig().getId());
        if(future != null)
        {
            messageFutureMap.remove(csNioMessage.getConfig().getId());
            future.complete(csNioMessage);
        }
    }

    public static boolean checkAndConnect()
    {
        for(ExportClientDealServer dealServer:dealServerList)
        {
            dealServer.connect();
        }

        return ExportClientSocketManager.dealServerList.size() > 0;
    }

    private static ExportClientDealServer getDealServer()
    {
        if(nextServerInt >= 125)
        {
            nextServerInt = 0;
        }

        int nextIndex = nextServerInt % dealServerList.size();
        nextServerInt++;

        ExportClientDealServer dealServer = dealServerList.get(nextIndex);
        return dealServer;
    }

    public static TransferMessageDto sendDataToServer(TransferMessageDto po,ExportClientDealServer dealServer) {
        TransferMessageDto resultPo = po.convertNewResultMessage();
        try {
            if(dealServer == null)
            {
                dealServer = getDealServer();
            }

            if (dealServer == null) {
                resultPo.getConfig().setDealResult(ExportDealResultTypeEnum.fail.code);
                resultPo.getConfig().setErrorMessage("服务地址不存在");
                return resultPo;
            }

            CompletableFuture completeFuture = new CompletableFuture();
            messageFutureMap.put(po.getConfig().getId(), completeFuture);

            dealServer.sendMessage(po);
            return getMessageFutureResult(completeFuture,resultPo);
        }
        catch (Exception ex)
        {
            resultPo.getConfig().setDealResult(ExportDealResultTypeEnum.fail.code);
            resultPo.getConfig().setErrorMessage("等待处理异常："+ex.getMessage());
            return resultPo;
        }
    }

    public static TransferMessageDto sendDataToServer(TransferMessageDto po, Channel channel,boolean waitReturnValue) {
        TransferMessageDto resultPo = po.convertNewResultMessage();
        try {
            if(waitReturnValue)
            {
                CompletableFuture completeFuture = new CompletableFuture();
                messageFutureMap.put(po.getConfig().getId(), completeFuture);
                channel.writeAndFlush(po);
                return getMessageFutureResult(completeFuture,resultPo);
            }
            else
            {
                channel.writeAndFlush(po);
            }

            return null;
        }
        catch (Exception ex)
        {
            resultPo.getConfig().setDealResult(ExportDealResultTypeEnum.fail.code);
            resultPo.getConfig().setErrorMessage("等待处理异常："+ex.getMessage());
            return resultPo;
        }
    }

    private static TransferMessageDto getMessageFutureResult(CompletableFuture completeFuture,TransferMessageDto resultPo)
    {
        try {
            Object dealResultObj = completeFuture.get(310, TimeUnit.SECONDS);
            if (dealResultObj != null) {
                return (TransferMessageDto) dealResultObj;
            }

            resultPo.getConfig().setDealResult(ExportDealResultTypeEnum.fail.code);
            resultPo.getConfig().setErrorMessage("等待处理异常：未获取到数据");
            return resultPo;
        }
        catch (Exception ex)
        {
            resultPo.getConfig().setDealResult(ExportDealResultTypeEnum.fail.code);
            resultPo.getConfig().setErrorMessage("等待处理异常："+ex.getMessage());
            return resultPo;
        }
    }
}
